package com.invengo.testrfid.mvp.ui.activity.test;

import android.app.Activity;
import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.util.SparseIntArray;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.google.gson.reflect.TypeToken;
import com.invengo.testrfid.R;
import com.invengo.testrfid.app.entity.BindEntity;
import com.invengo.testrfid.app.entity.MessageEntity;
import com.invengo.testrfid.app.utils.GsonUtils;
import com.invengo.testrfid.app.utils.MyLogUtils;
import com.invengo.testrfid.app.utils.ShareSaveUtils;
import com.invengo.testrfid.app.utils.WifiStatueUtils;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.callback.StringCallback;
import com.lzy.okgo.model.Response;

import java.util.ArrayList;
import java.util.List;

import invengo.javaapi.core.BaseReader;
import invengo.javaapi.core.IMessageNotification;
import invengo.javaapi.core.Util;
import invengo.javaapi.handle.IMessageNotificationReceivedHandle;
import invengo.javaapi.protocol.IRP1.PowerOff;
import invengo.javaapi.protocol.IRP1.RXD_TagData;
import invengo.javaapi.protocol.IRP1.ReadTag;
import invengo.javaapi.protocol.IRP1.Reader;
import invengo.javaapi.protocol.IRP1.WriteEpc;
import invengo.javaapi.protocol.IRP1.WriteUserData_6C;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

public class MainActivity extends AppCompatActivity implements IMessageNotificationReceivedHandle {

    SoundPool soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100);
    SparseIntArray soundPoolMap = new SparseIntArray();
//    String byIp = "10.15.64.1:8099";  // 内网正式环境
    private Reader reader;
    private String TAG = "readTag";
    private TextView tv_tid;
    private EditText et_c_no;
    private Button btn_upload;
    private boolean isStopReadTag = false;
    private List<BindEntity> bindEntities;
    private int position = 0;
    private String byIp = "47.104.26.251:8090"; // 外网测试

    public static byte[] intToByteArray(int a) {
        return new byte[]{
                (byte) ((a >> 24) & 0xFF),
                (byte) ((a >> 16) & 0xFF),
                (byte) ((a >> 8) & 0xFF),
                (byte) (a & 0xFF)
        };
    }

    public void showSoftInputFromWindow(Activity activity, EditText editText) {
        editText.setFocusable(true);
        editText.setFocusableInTouchMode(true);
        editText.requestFocus();
        activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_tid = findViewById(R.id.tv_tid);
        et_c_no = findViewById(R.id.et_c_no);
        btn_upload = findViewById(R.id.btn_upload);

        soundPoolMap.put(1, soundPool.load(this, R.raw.tag, 1));
        soundPoolMap.put(2, soundPool.load(this, R.raw.notag, 2));
    }

    @Override
    protected void onResume() {
        super.onResume();

        conntect();
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (reader.isConnected())
            reader.disConnect();
    }

    public void stopReadTag(View view) {

        if (isStopReadTag) {
            return;
        }
        isStopReadTag = true;

        //发送关功放指令，停止读卡
        boolean result = reader.send(new PowerOff());
        if (result) {

            Log.i(TAG, "stopSuccess");
//            showToast("发送成功");
        } else {
            Log.i(TAG, "stopFailede");
            showToast("发送失败");
        }
    }

    /**
     * 连接读写器
     */
    public void conntect() {

        Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<String> e) throws Exception {

                // 两种设备使用的连接方法是不一样的。
                String address = "/dev/ttyS4" + "," + "115200";
                Log.i(TAG, "address___" + address);
                reader = new Reader("Reader1", "RS232", address);
                if (reader.connect()) {
                    e.onNext("success");
                } else {
                    e.onNext("error");
                }
            }
        }).subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread());

        observable.subscribe(new Consumer<String>() {
            @Override
            public void accept(@NonNull String s) throws Exception {

                if (s.contains("success")) {
                    onConnectSuccess();
                } else {
                    Log.i(TAG, "connectFailed");
                }
            }
        });
    }

    public void onConnectSuccess() {

        Log.i(TAG, "connectSuccess");
        reader.onMessageNotificationReceived.add(MainActivity.this);
    }

    /**
     * 获取标签数据的回调方法
     *
     * @param baseReader
     * @param msg
     */
    @Override
    public void messageNotificationReceivedHandle(BaseReader baseReader, IMessageNotification msg) {


        if (msg instanceof RXD_TagData) {
            final RXD_TagData data = (RXD_TagData) msg;

            Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
                @Override
                public void subscribe(@NonNull ObservableEmitter<String> e) throws Exception {

                    StringBuilder stringBuilder = new StringBuilder();
                    String tid = Util.convertByteArrayToHexString(data.getReceivedMessage().getTID());
                    stringBuilder.append("tid:" + tid + "\n");
                    Log.i(TAG, stringBuilder.toString());
                    e.onNext(tid);
                }
            }).subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread());

            observable.subscribe(new Consumer<String>() {
                @Override
                public void accept(@NonNull String s) throws Exception {

                    tv_tid.setText(s);

                    showSoftInputFromWindow(MainActivity.this, et_c_no);
                    playSound(1, 0);
                    stopReadTag(null);
                }
            });
        }
    }

    /**
     * 写标签epc
     *
     * @param view
     */
    public void writeTagEpc(View view) {

        if (reader == null || !reader.isConnected()) {
            showToast("读写器未连接");
            conntect();
            return;
        }

        WriteEpc data_6C = new WriteEpc((byte) 0x00, intToByteArray(0000), intToByteArray(0x9999ffff));
        boolean result = reader.send(data_6C);
        if (result) {
            Log.i(TAG, "writeEpcSuccess");
            showToast("发送写入指令成功");
        } else {
            Log.i(TAG, "writeEpcFailed");
            showToast("发送写入指令失败");
        }
    }

    public void writeTagUser(View view) {


        if (reader == null || !reader.isConnected()) {
            showToast("读写器未连接");
            conntect();
        }

        WriteUserData_6C data_6C = new WriteUserData_6C((byte) 0x00, intToByteArray(0000), 2, intToByteArray(0x88880000));
        boolean result = reader.send(data_6C);
        if (result) {
            Log.i(TAG, "writeTagUser: success");
            showToast("发送写入指令成功");
        } else {
            Log.i(TAG, "writeTagUser: failed");
            showToast("发送写入指令失败");
        }
    }

    /**
     * 读取标签
     */
    public boolean readTag(View view) {


        if (reader == null || !reader.isConnected()) {
            showToast("读写器未连接");
            conntect();
            return false;
        }

        //发送读卡指令，读取6C标签EPC
        ReadTag readTag = new ReadTag(ReadTag.ReadMemoryBank.EPC_TID_UserData_6C);
        boolean result = reader.send(readTag);
        if (result) {
            Log.i(TAG, "sendReadSuccess");
//            showToast("发送成功");

            isStopReadTag = false;
            return true;
        } else {

            playSound(2, 0);
            Log.i(TAG, "sendReadFailed");
            showToast("发送失败");
            return false;
        }
    }

    public void showToast(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

    private boolean show(String key) {

        return true;
    }

    /**
     * 将数据发送到服务器
     *
     * @param view
     */
    public void sendData(View view) {

        String cageID = et_c_no.getText().toString();
        if (cageID.length() <= 0) {
            showToast("请输入笼车编号！");
            playSound(2, 0);
            return;
        }

        if (cageID.length() != 4) {

            playSound(2, 0);
            showToast("请输入正确笼车编号！");
            return;
        }

        String tid = tv_tid.getText().toString();
        if (tid.length() <= 0) {

            playSound(2, 0);
            showToast("请扫描标签！");
            return;
        }

        if (WifiStatueUtils.isWife()) {
            sendData(tid, cageID);
        } else {

            playSound(2, 1);
            saveToLocal(tid, cageID);
        }
    }

    /**
     * 数据上传
     *
     * @param view
     */
    public void uploadData(View view) {

        position = 0;
        if (WifiStatueUtils.isWife()) {

            String x = ShareSaveUtils.getStringFromTable("data");
            bindEntities = (List<BindEntity>) GsonUtils.jsonToList(x, new TypeToken<List<BindEntity>>() {
            }.getType());
            localSnedData();
        } else {

            showToast("无网络！！！");
        }
    }

    private void localSnedData() {

        if (position < bindEntities.size()) {
            BindEntity bindEntity = bindEntities.get(position);
            sendData2(bindEntity.getTid(), bindEntity.getCageNo());
        } else {

            position = 0;
            bindEntities.clear();
            showToast("数据全部上传成功");
            btn_upload.setText("数据上传");
            ShareSaveUtils.saveStringInTable("data", "null");
        }
    }

    /**
     * 保存到本地
     *
     * @param tid
     * @param cageNo
     */
    private void saveToLocal(final String tid, final String cageNo) {

        Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {

                String x = ShareSaveUtils.getStringFromTable("data");
                List<BindEntity> bindEntities = new ArrayList<>();
                if (!x.equals("null") && x.length() > 0) {
                    List<BindEntity> bindEntitiesLocal = (List<BindEntity>) GsonUtils.jsonToList(x, new TypeToken<List<BindEntity>>() {
                    }.getType());
                    bindEntities.addAll(bindEntitiesLocal);
                }
                BindEntity bindEntity = new BindEntity(tid, cageNo);
                bindEntities.add(bindEntity);
                ShareSaveUtils.saveStringInTable("data", GsonUtils.objectToJson(bindEntities));
                emitter.onNext(bindEntities.size() + "");
            }
        });
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String data) throws Exception {

                btn_upload.setText("数据上传       " + data);
                et_c_no.setText("");
                tv_tid.setText("Tid");
            }
        };
        observable.subscribeOn(Schedulers.computation())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(consumer);

    }

    /**
     * 网络请求
     */
    private void sendData(String tid, String cageNo) {

        String t = "http://" + byIp + "/api/CageInfo/CageInitialize?tid=" + tid + "&cageNo=京烟" + cageNo;
        OkGo.<String>get(t)
                .tag(this)
                .execute(new StringCallback() {

                    @Override
                    public void onSuccess(Response<String> response) {

                        playSound(1, 0);
                        MyLogUtils.log(TAG, "success" + response.body(), 4);
                        showMessage(response.body());
                    }

                    @Override
                    public void onError(Response<String> response) {

                        playSound(2, 0);
                        MyLogUtils.log(TAG, "failed" + response.body(), 4);
                        showToast("请求失败！检查网络！");
                    }
                });
    }

    /**
     * 网络请求,数据插入成功。
     */
    private void sendData2(String tid, String cageNo) {


        String t = "http://" + byIp + "/api/CageInfo/CageInitialize?tid=" + tid + "&cageNo=京烟" + cageNo;
        OkGo.<String>get(t)
                .tag(this)
                .execute(new StringCallback() {

                    @Override
                    public void onSuccess(Response<String> response) {

                        playSound(1, 0);
                        position++;
                        localSnedData();
                    }

                    @Override
                    public void onError(Response<String> response) {

                        position++;
                        localSnedData();
                    }
                });
    }

    /**
     * data
     * <p>
     * {"Status":0,"Info":"笼车RFID编号 12323 已经初始化，请换标签重试"}
     *
     * @param message
     */
    private void showMessage(String message) {


        MessageEntity messageEntity = (MessageEntity) GsonUtils.jsonToBean(message, MessageEntity.class);

        if (messageEntity.getStatus().equals("0")) {

            playSound(2, 0);
            showToast("插入失败" + messageEntity.getInfo());
            et_c_no.setText("");
        } else {

            showToast("插入成功！");
            playSound(1, 2);
            et_c_no.setText("");
            tv_tid.setText("Tid");
        }
    }


    /**
     * 声音
     *
     * @param sound
     * @param loop
     */
    public void playSound(int sound, int loop) {

        AudioManager mgr = (AudioManager) this
                .getSystemService(Context.AUDIO_SERVICE);
        float streamVolumeCurrent = mgr
                .getStreamVolume(AudioManager.STREAM_MUSIC);
        float streamVolumeMax = mgr
                .getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        float volume = streamVolumeCurrent / streamVolumeMax;
        soundPool.play(soundPoolMap.get(sound), volume, volume, 1, loop, 1f);
        // 参数：1、Map中取值 2、当前音量 3、最大音量 4、优先级 5、重播次数 6、播放速度
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        return super.onKeyUp(keyCode, event);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

//        showToast(keyCode + "");
        if (keyCode != 2) {
            return super.onKeyDown(keyCode, event);
        } else {
            readTag(null);
            return true;
        }
    }
}
